// 参考：https://www.jianshu.com/p/8d303ff8fdeb
// 仿 SQL 存储
import fs from "fs-extra"
import { getPathFromDir, formatTime, modifyFileName } from "../util/index.js"

export interface DataModel {
  key: string,
  value: string[]
}
export type SqlData = Record<string, string[]>

export default class Sql {
  cached: SqlData
  WRITR_FILE_PATH = getPathFromDir("sql.json")

  constructor() {
    try {
      fs.ensureDirSync("uploads")
      this.cached = fs.readJsonSync(this.WRITR_FILE_PATH) as SqlData
    } catch (error) {
      this.cached = { "length": ["0"] }
      fs.writeJSONSync(this.WRITR_FILE_PATH, this.cached)
    }
  }

  public start(fn: () => void): void {
    if (this.cached) fn()
  }

  public close(fn?: () => void): void {
    // 仍然有值
    if (this.cached) {
      // 写入文件
      fs.writeJSONSync(this.WRITR_FILE_PATH, this.cached)
    }
    // 预处理关闭事件
    fn && fn()
  }

  public backup(): Promise<undefined> {
    fs.ensureDirSync("logs")
    fs.writeJSONSync(`logs/sql-${formatTime(Date.now())}.json`, this.cached)
    return Promise.resolve(undefined)
  }

  public write(data: DataModel): void {
    const target = this.cached[data.key] || []
    // 不存在
    if (!target) this.cached[data.key] = [];
    // 合并数组
    this.cached[data.key] = target.concat(data.value)
    // 添加长度
    const len = data.value.length + Number(this.cached.length[0])
    this.cached.length = [len.toString()]
    // 非生产输出信息
    if (process.env.NODE_ENV !== 'production') {
      console.log(this.cached);
    }
  }

  public read(key: string): string[] {
    return this.cached[key] || []
  }

  public setInvaildFile(key: string, name: string): void {
    const arr = this.cached[key]
    if (!arr[0]) throw new Error("Cound not found ip")
    // 如果图片存在
    if (arr && arr.includes(name)) {
      let index = arr.indexOf(name)
      let newName = name + ".invalid"
      arr[index] = newName
      try {
        modifyFileName(`uploads/${name}`, `uploads/${newName}`)
      } catch (error) {
        throw error
      }
    }
  }

  public getSize(): number {
    return Number(this.cached['length'][0])
  }

  public getAll(): string[] {
    let result: string[] = []
    for (const key in this.cached) {
      if (key === 'length') continue;
      let val = this.cached[key]
      result = result.concat(val)
    }
    return result
  }
}
